package com.evil.kingdom.service.person.soldier.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.evil.common.core.util.StreamUtil;
import com.evil.kingdom.pojo.dto.person.base.PersonDto;
import com.evil.kingdom.pojo.dto.person.soldier.SoldierDto;
import com.evil.kingdom.pojo.entity.person.base.Person;
import com.evil.kingdom.pojo.entity.person.soldier.Soldier;
import com.evil.kingdom.pojo.enums.PersonTypeEnum;
import com.evil.common.mongo.service.impl.SingleServiceImpl;
import com.evil.kingdom.repository.person.soldier.SoldierRepository;
import com.evil.kingdom.service.person.base.PersonService;
import com.evil.kingdom.service.person.soldier.SoldierService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 士兵
 *
 * @author liyang
 * @date 2024-05-22 17:46
 */
@Slf4j
@Service
@AllArgsConstructor
public class SoldierServiceImpl extends SingleServiceImpl<SoldierRepository, Soldier> implements SoldierService {

    private final PersonService personService;

    @Override
    public PersonTypeEnum type() {
        return PersonTypeEnum.SOLDIER;
    }

    @Override
    public Optional<SoldierDto> isExistDtoByName(String name) {
        return personService.isExistByName(name).flatMap(this::isExistDtoByPerson);
    }

    @Override
    public SoldierDto findDtoByName(String name) {
        return this.findDtoByPerson(personService.findByName(name));
    }

    @Override
    public List<SoldierDto> isExistDtoListByNames(Collection<String> names) {
        if (CollectionUtil.isEmpty(names)) {
            return new ArrayList<>();
        }
        List<PersonDto> persons = personService.findDtoByNames(names);
        Map<String, PersonDto> personMap = StreamUtil.toMapK(persons, PersonDto::getName);

        List<Soldier> soldiers = this.isExistByNames(personMap.keySet());
        return this.toDto(personMap, soldiers);
    }

    @Override
    public List<SoldierDto> findDtoListByNames(Collection<String> names) {
        if (CollectionUtil.isEmpty(names)) {
            return new ArrayList<>();
        }
        List<PersonDto> persons = personService.findDtoByNames(names);
        Map<String, PersonDto> personMap = StreamUtil.toMapK(persons, PersonDto::getName);

        List<Soldier> soldiers = this.findByNames(personMap.keySet());
        return StreamUtil.transListT(soldiers, soldier -> this.toDto(personMap.get(soldier.getName()), soldier));
    }

    @Override
    public Optional<SoldierDto> isExistDtoByPerson(Person person) {
        return this.isExistDtoByPersonDto(personService.findDtoByPerson(person));
    }

    @Override
    public SoldierDto findDtoByPerson(Person person) {
        return this.findDtoByPersonDto(personService.findDtoByPerson(person));
    }

    @Override
    public Optional<SoldierDto> isExistDtoByPersonDto(PersonDto personDto) {
        return this.isExistByName(personDto.getName()).map(e -> this.toDto(personDto, e));
    }

    @Override
    public SoldierDto findDtoByPersonDto(PersonDto personDto) {
        Soldier soldier = this.findByName(personDto.getName());
        return this.toDto(personDto, soldier);
    }

    private List<SoldierDto> toDto(Map<String, PersonDto> personMap, Collection<Soldier> soldiers) {
        List<String> unExist = StreamUtil.transListTF(soldiers, Soldier::getName, n -> !personMap.containsKey(n));
        if (!unExist.isEmpty()) {
            this.throwNotExist(unExist);
        }
        return StreamUtil.transListT(soldiers, soldier -> this.toDto(personMap.get(soldier.getName()), soldier));
    }

    private SoldierDto toDto(PersonDto person, Soldier soldier) {
        SoldierDto soldierDto = BeanUtil.copyProperties(person, SoldierDto.class);
        BeanUtil.copyProperties(soldier, soldierDto);
        return soldierDto;
    }
}
